package com.etnoe.gis.common.utils;

import com.etnoe.gis.common.domain.CoordDistance;
import com.etnoe.gis.common.domain.Gps;
import com.etnoe.gis.common.domain.LonLatConvert;
import com.etnoe.gis.erro.CustomParameterizedException;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author 张任豪
 * Gis相关功能工具类
 */
@Slf4j
public class GisUtil {


    /**
     * 计算两个经纬度之间的距离
     * @param lon1 经度1
     * @param lat1 纬度1
     * @param lon2 经度2
     * @param lat2 纬度2
     * @return
     */
    public static double distance(double lon1, double lat1, double lon2, double lat2) {
        double x = Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.cos((lon1 - lon2) * Math.PI / 180);
        double y = Math.sin(lat1 * Math.PI / 180) * Math.sin(lat2 * Math.PI / 180);
        double s = x + y;
        if (s > 1) { s = 1; }
        if (s < -1) { s = -1; }
        double alpha = Math.acos(s);
        double distance = alpha * 6371.01 * 1000;
        return new BigDecimal(distance).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 单个经纬度转换
     * @param fLat 纬度
     * @param fLon 经度
     * @param srcLonLat 源经纬度(1:wps84、2:gcj02、3:百度bd0911、4：百度mc)
     * @param tgtLonLat 目标经纬度(1:wps84、2:gcj02、3:百度bd0911、4：百度mc)
     * @param returnType 转换结果(1表示返回经度，2表示返回纬度，否则返回经纬度)
     * @return
     */
    public static String lonLatConvert(double fLat, double fLon, int srcLonLat, int tgtLonLat, int returnType) {
        Gps gps;
        try {
            // 默认是传纬度经度，如果出现经度纬度也能实现，交换一下位置即可
            if (fLat > fLon) {
                double tmp = fLat;
                fLat = fLon;
                fLon = tmp;
            }

            // 1：google卫星坐标gps84、2：google地图gcj02、3：百度0911、4：百度mc
            if (srcLonLat == 2 && tgtLonLat == 1) {
                gps = GpsUtil.gcj_To_Gps84(fLat, fLon);
            } else if (srcLonLat == 3 && tgtLonLat == 1) {
                gps = GpsUtil.bd09ll_To_Gps84(fLat, fLon);
            } else if (srcLonLat == 4 && tgtLonLat == 1) {
                gps = GpsUtil.bd09mc_To_Gps84(fLat, fLon);
            } else if (srcLonLat == 1 && tgtLonLat == 2) {
                gps = GpsUtil.gps84_To_Gcj02(fLat, fLon);
            } else if (srcLonLat == 3 && tgtLonLat == 2) {
                gps = GpsUtil.bd09ll_To_Gcj02(fLat, fLon);
            } else if (srcLonLat == 4 && tgtLonLat == 2) {
                gps = GpsUtil.bd09mc_To_Gcj02(fLat, fLon);
            } else if (srcLonLat == 1 && tgtLonLat == 3) {
                gps = GpsUtil.gps84_To_Bd09ll(fLat, fLon);
            } else if (srcLonLat == 2 && tgtLonLat == 3) {
                gps = GpsUtil.gcj02_To_Bd09ll(fLat, fLon);
            } else if (srcLonLat == 4 && tgtLonLat == 3) {
                gps = GpsUtil.bd09mc_To_Bd09ll(fLat, fLon);
            } else {
                gps = new Gps(fLat, fLon);
            }

            if (gps != null) {
                // 1表示返回经度，2表示返回纬度，否则返回经纬度
                if (returnType == 1) {
                    return gps.getWgLon() + "";
                } else if (returnType == 2) {
                    return gps.getWgLat() + "";
                } else {
                    double wgLon = BigDecimal.valueOf(gps.getWgLon()).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double wgLat = BigDecimal.valueOf(gps.getWgLat()).setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
                    return wgLon + "," + wgLat;
                }
            }
        } catch (Exception e) {
            log.error("", e);
            throw new CustomParameterizedException(e.getLocalizedMessage());
        }
        return "";
    }

    public static List<CoordDistance> countDistances(List<CoordDistance> coords) {
        for (CoordDistance coord : coords) {
            double distance = distance(coord.getLon1(), coord.getLat1(), coord.getLon2(), coord.getLat2());
            coord.setDistance(distance);
        }
        return coords;
    }

    public static List<LonLatConvert> batchLonLat(List<LonLatConvert> lonLatConverts) {
        if (lonLatConverts.isEmpty()){
            throw new CustomParameterizedException("解析异常");
        }
        for (LonLatConvert lonLatConvert : lonLatConverts) {
            String result = lonLatConvert(lonLatConvert.getLat(), lonLatConvert.getLon(), lonLatConvert.getSrcLonLat(), lonLatConvert.getTgtLonLat(), 3);
            lonLatConvert.setResult(result);
        }
        return lonLatConverts;
    }
}
